﻿using DidaCode.Workflow.Help;
using DidaCode.Workflow.Logs;
using DidaCode.Workflow.Models;
using DidaCode.Workflow.Models.Parameters;
using DidaCode.Workflow.Models.Results;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DidaCode.Workflow.NodeBase
{
    public class Workflow<TInput, TOutput> where TOutput : new()
    {
        private readonly List<INode<TInput, TOutput>> _nodes;

        public Workflow()
        {
            _nodes = new List<INode<TInput, TOutput>>();

            foreach (var rootNodeConfig in NodeConfig.RootConfig)
            {
                // var rootNode = CreateNodeTree<HotelSearchParameter, HotelSearchResult>(rootNodeConfig.Key, rootNodeConfig.Value);
                var rootNode = CreateNodeTree(rootNodeConfig.Key, rootNodeConfig.Value);
                AddNode(rootNode);
            }
        }

        public void AddNode(INode<TInput, TOutput> node)
        {
            _nodes.Add(node);
        }

        public async Task<NodeResult<TOutput>> ExecuteAsync(TInput input)
        {
            var output = new TOutput();
            var context = new ExecutionContext<TInput, TOutput>(input, output);
            return await ExecuteAsync(context).ConfigureAwait(false);
        }



        public async Task<NodeResult<TOutput>> ExecuteAsync(TInput input, TOutput output)
        {
            var context = new ExecutionContext<TInput, TOutput>(input, output);
            return await ExecuteAsync(context).ConfigureAwait(false);
        }



        /// <summary>
        /// 执行工作流节点
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        private async Task<NodeResult<TOutput>> ExecuteAsync(ExecutionContext<TInput, TOutput> context) 
        {
            ProcessDataStorage.Init();
            ExecutionLogger.LogResult("Init", new TypedResult(typeof(string), "节点初始化"));
            NodeResult<TOutput> result = default;
            try
            {
                foreach (var node in _nodes)
                {
                    var nodeResult = await node.ExecuteAsync(context).ConfigureAwait(false);
                    if (!nodeResult.IsSuccess)
                    {
                        var nodeName = NodeFactory.NodeName(node.GetType());
                        if (!NodeConfig.GetNodeConfig(nodeName).ContinueOnFailure) 
                        {
                            result = nodeResult;
                            Console.WriteLine($"{nodeName}被执行失败，终止执行");
                            break;
                        }
                        Console.WriteLine($"{nodeName}被执行失败，继续执行");
                        continue;
                    }
                    result = nodeResult;
                }
            }
            finally
            {
                ProcessDataStorage.Clear();
                // 清空日志数据
                ExecutionLogger.Clear();
            }
            return result;
        }


        /// <summary>
        /// <!--创建节点树-->
        /// </summary>
        /// <typeparam name="TInput"></typeparam>
        /// <typeparam name="TOutput"></typeparam>
        /// <param name="nodeName"></param>
        /// <param name="nodeConfig"></param>
        /// <returns></returns>
        public INode<TInput, TOutput> CreateNodeTree(string nodeName, NodeConfig nodeConfig)
        {
            // 创建根节点
            var node = NodeFactory.CreateNode<TInput, TOutput>(nodeName, nodeConfig.SwitchConfig);
            // 递归创建子节点
            if (nodeConfig.Children != null)
            {
                foreach (var childConfig in nodeConfig.Children)
                {
                    var childNode = CreateNodeTree(childConfig.Key, childConfig.Value);
                    node.AddChild(childNode);
                }
            }
            return node;
        }



        ///// <summary>
        ///// <!--创建节点树-->
        ///// </summary>
        ///// <typeparam name="TInput"></typeparam>
        ///// <typeparam name="TOutput"></typeparam>
        ///// <param name="nodeName"></param>
        ///// <param name="nodeConfig"></param>
        ///// <returns></returns>
        //public INode<TInput, TOutput> CreateNodeTree(string nodeName, NodeConfig nodeConfig)
        //{
        //    // 创建根节点
        //    var node = NodeFactory.CreateNode<TInput, TOutput>(nodeName, nodeConfig.SwitchConfig);

        //    // 递归创建子节点
        //    if (nodeConfig.Children != null)
        //    {
        //        foreach (var childConfig in nodeConfig.Children)
        //        {
        //            var childNode = CreateChildNodeTree(childConfig.Key, childConfig.Value);
        //            node.AddChild(childNode);
        //        }
        //    }

        //    return node;
        //}

        ///// <summary>
        ///// 创建子节点树
        ///// </summary>
        ///// <typeparam name="TInput"></typeparam>
        ///// <typeparam name="TOutput"></typeparam>
        ///// <param name="nodeName"></param>
        ///// <param name="nodeConfig"></param>
        ///// <returns></returns>
        //public INode<TOutput, TOutput> CreateChildNodeTree(string nodeName, NodeConfig nodeConfig)
        //{
        //    // 创建子节点
        //    var node = NodeFactory.CreateNode<TOutput, TOutput>(nodeName, nodeConfig.SwitchConfig);

        //    // 递归创建子节点
        //    if (nodeConfig.Children != null)
        //    {
        //        foreach (var childConfig in nodeConfig.Children)
        //        {
        //            var childNode = CreateChildNodeTree(childConfig.Key, childConfig.Value);
        //            node.AddChild(childNode);
        //        }
        //    }
        //    return node;
        //}
    }
}
